GCM!!

最近又出現一些新的狀況,主要是因為 Android 的 Shared Preferences 不太可靠的關係。

而且我們主要目標對象是公車站牌(Android 板子),希望有遠端更新,遠端操作…。

並期望放出就能自主活得好好滴。

但是存放在 Shared Preferences 的站牌ID,就隨著多次操作後就跟著 Shared Preferences 一同消失了!

可以參考下面這篇:

在他們的例子,會有將近 0.2% ~ 0.3% 使用者的 Shared Preferences 會遺失掉。

推薦的解決方式是使用 DB。

於是我們也就緊急發佈出 DB 版本。

但是已經消失的該怎麼辦哩??


於是將矛頭轉到 GCM,但是聽說要使用 GCM 的必須登入 Google Account。

此時心想不太對,因為外面站牌都未登入 Google,雖然「再」大痛一次,就可以玩更多花樣,也預期能比較好維護。

所以還先看一下使用限制會比較保險:

  • 最低要求,GCM 需要執行在Android版本 2.2 以上且同時安裝Google Play Store APP

  • 如果你想要透過Google Play Services使用GCM的新功能,Device 需要執行在Android版本 2.3 以上

  • 在pre-3.0 需要設定 Google Account,但是 4.0.4 以後可以不用設定 Google Account

看完不用 Google Account 終於鬆了一口氣。

在實驗的過程中,發現 GCM 需要 Google Play Services,然後得去 Google Store 設定帳號下載。

PS :不過可以事先把 Google Play Services APP dump 出來,然後直接安裝也算。

接著主要參考下面兩篇,實作GCM:

build.gradle
1
2
3
dependencies {
compile "com.google.android.gms:play-services:7.0.0"
}
Android SDK(GCM)
1
2
3
4
5
6
id: 126 or "extra-android-m2repository"
Type: Extra
Desc: Android Support Repository, revision 13
id: 127 or "extra-android-support"
Type: Extra
Desc: Android Support Library, revision 22.1
1
2
3
4
5
6
7
8
9
10
11
12
13
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<application>
<!-- ... -->
<receiver android:name=".MyReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >

<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="YOUR_PACKAGE_NAME" />
</intent-filter>
</receiver>
</application>

當 GCM 傳送訊息給你的 app 時, BroadcastReceiver 會收到訊息(intent),你的可以在 BroadcastReceiver 處理這條 intent,或者交給 Service 處理(通常是IntentService)。

如果你用 Service 的話,你的 BroadcastReceiver 需繼承自 WakefulBroadcastReceiver, to hold a wake lock while the service is doing its work

GcmBroadcastReceiver.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;

public class GcmBroadcastReceiver extends BroadcastReceiver {

private static final String TAG = "GCM";

@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.i(TAG, "GcmBroadcastReceiver");

GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String messageType = gcm.getMessageType(intent);
Log.i(TAG, "GcmBroadcastReceiver messageType:"+messageType);

Bundle extras = intent.getExtras();
if (!extras.isEmpty()) {
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {

} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {

} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
Log.i(TAG,"Message GET");
}
Log.i(TAG, "GcmBroadcastReceiver Received: " + extras.toString());
}

}

}

Server 端則先用 python。python-gcm